import 'package:riki_router/utils/riki_event_log_util.dart';
import 'package:riki_router/utils/riki_router_exception.dart';

import 'riki_event_type.dart';
import 'riki_event_listener.dart';

export 'riki_event_type.dart';
export 'riki_event_listener.dart';
export 'riki_event_notify.dart';

/// 负责模块间通讯
/// 每个模块确保仅监听一次，后续通知逻辑每个模块间再次进行模块中分发
class RikiEvent {
  static const String _TAG = 'RikiEvent';
  static const String _ALL = 'RIKI_EVENT';

  // 工厂模式
  factory RikiEvent() => _getInstance();

  static RikiEvent get instance => _getInstance();
  static RikiEvent? _instance;

  RikiEvent._internal();

  static RikiEvent _getInstance() {
    if (_instance == null) {
      _instance = RikiEvent._internal();
    }
    return _instance!;
  }

  void init({bool debug = false}) {
    RikiEventLogUtil.init(isDebug: debug);
  }

  List<String> _registerPackage = [];
  Map<String, List<RikiEventListener>> _eventListeners = {_ALL: <RikiEventListener>[]};

  /// 添加事件监听
  /// [package] 模块名称，例如RikiIM
  /// [listener] 分发通知
  void addListener(String package, RikiEventListener listener) {
    RikiEventLogUtil.v('---------------------------RikiEvent--------------------------------');
    if (!_registerPackage.contains(package)) {
      if (listener.registerEvents.isEmpty) {
        _eventListeners[_ALL]?.add(listener);
        RikiEventLogUtil.v('$listener($package):注册全部类型监听');
      } else {
        if (listener.registerEvents.contains(_ALL)) {
          throw RikiRouterException(_TAG, '$listener($package):存在异常监听类型');
        }
        listener.registerEvents.forEach((type) {
          if (_eventListeners[type] == null) {
            _eventListeners[type] = <RikiEventListener>[];
          }
          _eventListeners[type]!.add(listener);
          RikiEventLogUtil.v('$listener($package):注册$type类型监听');
        });
      }
      _registerPackage.add(package);
    } else {
      throw RikiRouterException(_TAG, '$listener($package):已经注册过监听！！！！');
    }
    RikiEventLogUtil.v('---------------------------RikiEvent--------------------------------');
  }

  /// 移除事件监听
  void removeListener(RikiEventListener listener, {String? package}) {
    RikiEventLogUtil.v('---------------------------RikiEvent--------------------------------');
    for (MapEntry<String, List<RikiEventListener>> entry in _eventListeners.entries) {
      bool remove = entry.value.remove(listener);
      if (remove && entry.key == _ALL) {
        RikiEventLogUtil.v('$listener:取消全部类型监听');
        return;
      } else if (remove) {
        RikiEventLogUtil.v('$listener:取消${entry.key}类型监听');
      }
    }
    if (package != null) {
      _registerPackage.remove(package);
    }
    RikiEventLogUtil.v('---------------------------RikiEvent--------------------------------');
  }

  /// 发送事件
  /// [type] 时间类型，RikiMiddlewareEventType.value实际为字符串
  /// [arguments] 参数，因解耦关系，仅可传输基础数据类型，String/int/double/Map/List等
  /// [completer] 回调，有需要返回信息时使用
  void fire(RikiEventType type, [dynamic arguments, dynamic completer]) {
    if (!type.isCompliance) {
      throw RikiRouterException(_TAG, 'RikiEventType不符合命名规范');
    }
    RikiEventLogUtil.v('---------------------------RikiEvent--------------------------------');
    RikiEventLogUtil.v('');
    RikiEventLogUtil.v('事件类型:${type.value}');
    RikiEventLogUtil.v('事件参数:$arguments');
    RikiEventLogUtil.v('发送位置:${type.package}');

    List<RikiEventListener> fireList = [];
    fireList.addAll(_eventListeners[_ALL] ?? []);
    fireList.addAll(_eventListeners[type.value] ?? []);

    RikiEventLogUtil.v('接收位置:$fireList');
    RikiEventLogUtil.v('');
    RikiEventLogUtil.v('---------------------------RikiEvent--------------------------------');

    fireList.forEach((listener) {
      listener.onRikiEvent(type, arguments, completer);
    });
  }
}
